package org.itboys.weixin.tools;

import java.util.*;

import org.apache.commons.lang3.StringUtils;
import org.itboys.commons.utils.json.JsonUtils;
import org.itboys.commons.utils.time.TimeUtils;
import org.itboys.framework.spring.context.SpringContextHolder;
import org.itboys.redis.RedisCacheClient;
import org.itboys.weixin.cache.TokenCacheLoader;
import org.itboys.weixin.constant.WeixinConstants;
import org.itboys.weixin.dto.AccessToken;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONException;
import com.google.common.collect.Maps;
import org.itboys.weixin.entity.WeixinConfig;
import org.itboys.weixin.service.WeixinConfigService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 微信相关
 * @author ChenJunhui
 *
 */
public class WeixinUtils {

	private static Logger logger = LoggerFactory.getLogger(WeixinUtils.class);

	/**
	 * 用于暂存accessToken的map key为微信appId 会有定时线程定时清除的
	 */
	private static final Map<String, String> accessTokenMap = new HashMap<String, String>();
	private static Timer timer = null;
	private static final String CACHE_WX_ACCESS_TOKEN = "cache_wx_access_token_";

	/**
	 * 密钥交换token
	 * @param appId
	 * @param appSecret
	 * @return
	 */
	public static String getAccessToken(String appId, String appSecret) {
		WeixinConfigService weixinConfigService = SpringContextHolder.getBean("weixinConfigService");
		WeixinConfig weixinConfig = weixinConfigService.getByField("appId", appId);
		String accessToken = weixinConfig.getAccessToken();
		Date now=new Date();
		Date configDate=weixinConfig.getUpdateTime();
		System.out.println("当前时间=============================="+ TimeUtils.format(now,"yyyy-MM-dd HH:mm:ss"));
		System.out.println("更新时间=============================="+TimeUtils.format(configDate,"yyyy-MM-dd HH:mm:ss"));
		Long time=now.getTime()-configDate.getTime();
		if(time>3600000l||StringUtils.isBlank(accessToken)){
			accessToken = getAccessTokenToDataBase(weixinConfigService, weixinConfig);
		}
		return accessToken;
	}
	public static String getAccessTokenToDataBase(WeixinConfigService weixinConfigService,WeixinConfig weixinConfig) {
		String url= WeixinConstants.URL.FETCH_TOKEN_URL+"&appid="+weixinConfig.getAppId()+"&secret="+weixinConfig.getAppSecret();
		String jsonToken = HttpHelper.doGet(url);
		logger.info("************jsonToken************"+jsonToken);
		AccessToken token = JsonUtils.jsonToObject(AccessToken.class, jsonToken);
		String accessToken = token.getAccess_token();
		weixinConfigService.update(weixinConfig.getId(), "accessToken",accessToken);
		return accessToken;
	}

	/**
	 * 清除存在MAP中的缓存
	 * @param appId
	 */
	/*public static void cleanAccessToken(String appId){
		accessTokenMap.remove(appId);
	}*/

	/**
	 * 重新设置缓存中的token
	 * @param appId
	 * @param token
	 */
	/*public static void reSetAccessToken(String appId, String token){
		accessTokenMap.put(appId, token);
	}*/

	/**
	 * 取得token并放入变量里
	 * @param appId
	 * @param appScret
	 * @return
	 */
	private static synchronized String fetchAccessTokenAndSetToMap(String appId,String appScret, RedisCacheClient redisCacheClient) {
		String accessToken = accessTokenMap.get(appId);
		if(accessToken!=null){
			return accessToken;
		}
		String url=WeixinConstants.URL.FETCH_TOKEN_URL+"&appid="+appId+"&secret="+appScret;
		String jsonToken = HttpHelper.doGet(url);
		AccessToken token = JsonUtils.jsonToObject(AccessToken.class, jsonToken);
		accessToken = token.getAccess_token();
		redisCacheClient.set(CACHE_WX_ACCESS_TOKEN + appId, accessToken, 86400);
//		accessTokenMap.put(appId, accessToken);
		if(timer==null){
			timer = new Timer();
		}
		long delay = token.getExpires_in();
		if(delay>50){//其实有7200秒的有效时间 不知道有效时间会不会变 反正提前50秒去清空本地map的accessToken
			delay=delay-50;
		}
		timer.schedule(new ClearAccessTokenTask(appId, redisCacheClient), delay*1000);
		return accessToken;
	}

	static class ClearAccessTokenTask extends TimerTask{
		private String appId;
		private RedisCacheClient redisCacheClient ;
		public ClearAccessTokenTask(String appId, RedisCacheClient redisCacheClient){
			this.appId=appId;
			this.redisCacheClient = redisCacheClient;
		}
		@Override
		public void run() {
//			synchronized (accessTokenMap) {
//				accessTokenMap.remove(appId);
//			}
			redisCacheClient.del(CACHE_WX_ACCESS_TOKEN + appId);
		}
	}

	/**
	 * 获取生成二维码用的ticket
	 * @param action_name ： 二维码类型  QR_SCENE:临时二维码    QR_LIMIT_SCENE:永久二维码
	 * @param paramId : 参数ID
	 * @return
	 */
	public static String getTicket(String access_token, String action_name, Long paramId){
		try {
			Map<String, Object> param = Maps.newHashMapWithExpectedSize(3);
			param.put("expire_seconds", 604800);
			param.put("action_name", action_name);

			Map<String, Object> param2 = Maps.newHashMapWithExpectedSize(1);
			Map<String, Object> param3 = Maps.newHashMapWithExpectedSize(1);
			param3.put("scene_id", paramId);
			param2.put("scene", param3);
			param.put("action_info", param2);

			String result = HttpHelper.doJsonParamPost(WeixinConstants.URL.GET_TOWCODE_TICKET+access_token, JSON.toJSONString(param));
			return (String) JSON.parseObject(result).get("ticket");
		} catch (JSONException e) {
			e.printStackTrace();
		}
		return null;
	}

}
